/*************************************************************************
	> File Name: 8.3.1Sychronized--互斥锁.c
	> Author: Potter
	> Mail: tobewhatwewant@gmail.com
	> Created Time: 2014年09月16日 星期二 10时34分06秒
 ************************************************************************/

/* int pthread_join(pthread_t thread, void * * value_ptr);
 *  thread: 等待线程的标识
 *  value_ptr: 用户定义的指针，用来存储等待线程的返回值.
 *  return : 执行成功则返回0,失败则返回错误符号。函数返回值
 *
 *      县城创建完毕后，创建线程的线程可以使用 pthread_join() 函数等嗲
 *  被创建的线程的结束。pthread_join()函数会挂起自身线程的执行，直到指定的
 *  thraed结束. pthread_join()函数类似wait的函数，但是等待的是线程而不是进程
 *  . pthread_join()接收两个参数：线程ID和一个只想void * 类型变量的指针，
 *  用于接收线程的返回值。如果你对线程的返回值不敢兴趣，则将NULL作为第二个
 *  参数
 *
* int pthread_mutex_init(pthread_mutex_t * mutex, const thread_mutexattr_t * mutexattr)
* int pthread_mutex_lock(pthread_mutex_t * mutex)
* int pthread_mutex_trylock(pthread_mutex_t * mutex)
* int pthread_mutex_unlock(pthread_mutex_t * mutex)
* int pthread_mutex_destroy(pthread_mutex_t * mutex)
*
*   pthread_mutex_init()用来初始化mutex 并且使用mutexattr参数来传递
* 初始化mutex需要定义的属性，如果属性指针为NULL,则默认属性将赋予新建的临界区
*   pthread_mutex_lock()用来获得mutex，如果当前线程想要获取的mutex
* 已经被其他线程锁定，那么调用pthread_mutex_lock()将使得当前县城处于等待状态
*   pthread_mutex_trylock()和pthread_mutex_lock()功能基本一直，只不过是在
* "尝试"获得mutex,如果不能获得，将立刻返回，并继续县城的执行
*   pthread_mutex_unlock() 用来解放mutex锁，以便其他线程使用。在使用完毕
* mutex后，应该使用 pthread_mutex_destroy() 函数来释放 mutex 资源
* */

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>

pthread_mutex_t mutex; /*定义互斥锁*/
int lock_var; /*两个县城能修改的共享变量， 访问改变变量必须互斥*/

void pthread1(void * arg);
void pthread2(void * arg);

int main(int argc, char * argv[]) {
    pthread_t id1, id2;
    int ret;
    pthread_mutex_init(&mutex, NULL); /* 互斥锁初始化，新建临界区*/
    ret = pthread_create(&id1, NULL, (void *)pthread1, NULL); /*创建地一个线程*/
    if (ret != 0)
        fprintf(stdout, "pthread cread1\n");
    ret = pthread_create(&id2, NULL, (void *)pthread2, NULL); /*第二个线o程*/
    if(ret != 0)
        fprintf(stdout, "pthread cread2\n");

    pthread_join(id1, NULL); /*等待第一个线程结束*/
    pthread_join(id2, NULL); /*等待第二个线程结束*/
    
    pthread_mutex_destroy(&mutex); /*释放mutex资源*/ 

    exit(0);
}

void pthread1(void * arg) /*地一个线程执行代码*/
{
    int i;
    for(i=0; i<2; i++) {
        pthread_mutex_lock(&mutex); /*锁定临界区*/
        /* 临界区*/
        lock_var ++;
        fprintf(stdout, "pthread1: 第%d次循环,第1次打印 lock_var = %d\n", i, lock_var);
        sleep(1);
        fprintf(stdout, "pthread1: 第%d次循环,第2次打印 lock_var = %d\n", i,lock_var);
        /*已经完成了临界区的处理，解除对临界区的锁定。*/
        pthread_mutex_unlock(&mutex); /*解锁*/
        sleep(1);
    }
}

void pthread2(void * arg) /*第2个线程的执行代码*/
{
    int i;
    for(i=0; i<5; i++) {
        pthread_mutex_lock(&mutex); /*锁定临界区*/
        /*临界区*/
        sleep(1);
        lock_var ++;
        fprintf(stdout, "pthread2: 第%d次循环,第1次打印 lock_var = %d\n", i, lock_var);
        /*已经完成了临界区的处理，解除对临界区的锁定*/
        pthread_mutex_unlock(&mutex); /*解锁*/
        sleep(1);
    }
}
